﻿using ProgramCat.FiddlerExtension.Core.Utils.Crypto;
using ProgramCat.FiddlerExtension.Core.Utils.Winapi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Windows;

namespace ProgramCat.FiddlerExtension.Core.Utils
{
    /// <summary>
    /// 编码帮助类
    /// </summary>
    public static class EncodedHelp
    {

        /// <summary>
        /// url编码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="encodingType"></param>
        /// <param name="islow"></param>
        /// <returns></returns>
        public static string UrlEncode(this string code, EncodingType encodingType)
        {
            string res = "";
            try
            {
                var dt = GetEncoding(encodingType).GetBytes(code);
                res = HttpUtility.UrlEncode(dt);
            }
            catch { }
            return res;
        }
        /// <summary>
        /// url解码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="encodingType"></param>
        /// <param name="islow"></param>
        /// <returns></returns>
        public static string UrlDecode(this string code, EncodingType encodingType)
        {
            string res = "";
            try
            {
                res = HttpUtility.UrlDecode(code, GetEncoding(encodingType));
            }
            catch { }
            return res;
        }
        public static string Base64Encode(this string code, EncodingType encodingType)
        {
            string encode = "";
            try
            {
                var dt = GetEncoding(encodingType).GetBytes(code);
                encode = Convert.ToBase64String(dt);
            }
            catch{}
            return encode;
        }
        public static string Base64Decode(this string code, EncodingType encodingType)
        {
            string decode = "";
            try
            {
                byte[] bytes = Convert.FromBase64String(code);
                decode = GetEncoding(encodingType).GetString(bytes);
            }
            catch{}
            return decode;
        }

        /// <summary>
        /// 简体到繁体
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static string CHS2TW(this string code)
        {
            int len = code.Length;
            string _str = new string(' ', len) ;
            Kernel32api.LCMapStringEx("zh-CN", 0x04000000, code, len, _str, len, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            return _str;
        }
        /// <summary>
        /// 繁体到简体
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static string TW2CHS(this string code)
        {
            int len = code.Length;
            string _str = new string(' ', len);
            Kernel32api.LCMapStringEx("zh-CN", 0x02000000, code, len, _str, len, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            return _str;
        }
        /// <summary>
        /// 北京时间 转 格林威治时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ConvertDateTimeToString(this string time) 
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
            DateTime datetime;
            if (!DateTime.TryParse(time, out datetime))
            {
                
                return "";
            }
            long t = (datetime.Ticks - startTime.Ticks) / 10000;
            return t.ToString();
        }
        /// <summary>
        /// 格林威治时间戳 转 北京时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ConvertStringToDateTime(this string time)
        {
            if (time.Length != 10 && time.Length != 13)
            {
                return "";
            }
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            string timeTemp = time.Length == 13 ? time + "0000" : time + "0000000";
            long lTime = long.Parse(timeTemp);
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow).ToString();
        }

        public static string Escape(this string str)
        {
            return Microsoft.JScript.GlobalObject.escape(str).Trim();
        }
        public static string UnEscape(this string str)
        {
            return Microsoft.JScript.GlobalObject.unescape(str).Trim();
        }

        public static string Gb2312ToUtf8(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.UTF8).GetBytes(str);
            
            return GetEncoding(EncodingType.GB2312).GetString(Replace_0(gbkbs)).TrimEnd('\0');
        }

        public static string Utf8ToGb2312(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.GB2312).GetBytes(str);

            return GetEncoding(EncodingType.UTF8).GetString(Replace_0(gbkbs)).TrimEnd('\0');
        }

        public static string Ansi2unicode(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.UNICODE).GetBytes(str);
            return GetEncoding(EncodingType.GBK).GetString(Replace_0(gbkbs)).TrimEnd();
        }
        public static string unicode2Ansi(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.GBK).GetBytes(str);
            return GetEncoding(EncodingType.UNICODE).GetString(Replace_0(gbkbs)).TrimEnd('\0');
        }

        public static string UnicodeToutf8(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.GBK).GetBytes(str);
            gbkbs = Encoding.Convert(GetEncoding(EncodingType.UNICODE), GetEncoding(EncodingType.UTF8), gbkbs);

            return GetEncoding(EncodingType.GBK).GetString(Replace_0(gbkbs)).TrimEnd('\0');
        }
        public static string Utf8Tounicode(this string str)
        {
            byte[] gbkbs = GetEncoding(EncodingType.GBK).GetBytes(str);
            gbkbs = Encoding.Convert(GetEncoding(EncodingType.UTF8), GetEncoding(EncodingType.UNICODE), gbkbs);
            return GetEncoding(EncodingType.GBK).GetString(Replace_0(gbkbs)).TrimEnd('\0');
        }

        public static string GetMD4(this string str)
        { 
            return HashCrypt.Instance.GetMD4(str);
        }
        public static string GetMD5(this string str)
        {
            return HashCrypt.Instance.GetMD5(str);
        }
        public static string GetSHA1(this string str)
        {
            return HashCrypt.Instance.GetSHA1(str);
        }
        public static string GetSHA256(this string str)
        {
            return HashCrypt.Instance.GetSHA256(str);
        }
        public static string GetSHA512(this string str)
        {
            return HashCrypt.Instance.GetSHA512(str);
        }
        public static string GetCRC(this string str)
        {
            return HashCrypt.Instance.GetCRC(str);
        }

        public static byte[] Replace_0(byte[] bytes)
        {
            List<byte> vs = new List<byte>();
            for (int i = 0; i < bytes.Length; i++)
            {
                if (bytes[i] == '\0')
                {
                    break;
                    //continue;
                }
                vs.Add(bytes[i]);
            }
            return vs.ToArray();
        }

        public enum EncodingType
        {   
            GBK,
            UTF8,
            UNICODE,
            ASCII,
            GB2312,
            Default
        }
        public static Encoding GetEncoding(EncodingType encodingType)
        {
            Encoding encoding = Encoding.Default;
            switch (encodingType)
            {
                case EncodingType.GBK:
                    encoding = Encoding.GetEncoding("GBK");
                    break;
                case EncodingType.UTF8:
                    encoding = Encoding.UTF8;
                    break;
                case EncodingType.UNICODE:
                    encoding = Encoding.Unicode;
                    break;
                case EncodingType.ASCII:
                    encoding = Encoding.ASCII;
                    break;
                case EncodingType.GB2312:
                    encoding = Encoding.GetEncoding(936);
                    break;
                default:
                    encoding = Encoding.Default;
                    break;
            }
            return encoding;
        }
    }
}
